import CryptoJS from 'crypto-js';

/**
 * 显示消息提示框
 * @param content 提示的标题
 */
export function toast(content) {
    // 如果content超过20个字符，则用showModal显示
    if (content.length > 20) {
        uni.showModal({
            title: "提示",
            content: content,
            confirmText: "确定",
            showCancel: false,
            success: (res) => {
            }
        })
    } else {
        uni.showToast({
            icon: 'none',
            title: content
        })
    }
}

/**
 * 显示模态弹窗
 * @param content 提示的标题
 */
export function showConfirm(content) {
    return new Promise((resolve, reject) => {
        uni.showModal({
            title: '提示',
            content: content,
            cancelText: '取消',
            confirmText: '确定',
            success: function (res) {
                resolve(res)
            }
        })
    })
}

/**
 * 参数处理
 * @param params 参数
 */
export function tansParams(params) {
    let result = ''
    for (const propName of Object.keys(params)) {
        const value = params[propName]
        var part = encodeURIComponent(propName) + "="
        if (value !== null && value !== "" && typeof (value) !== "undefined") {
            if (typeof value === 'object') {
                for (const key of Object.keys(value)) {
                    if (value[key] !== null && value[key] !== "" && typeof (value[key]) !== 'undefined') {
                        let params = propName + '[' + key + ']'
                        var subPart = encodeURIComponent(params) + "="
                        result += subPart + encodeURIComponent(value[key]) + "&"
                    }
                }
            } else {
                result += part + encodeURIComponent(value) + "&"
            }
        }
    }
    return result
}


/**
 * 跳转页面
 * @param url
 */
export function goto(url) {
    this.$tab.navigateTo(url)
}



/**
 * ASE加密
 * @description 使用加密秘钥，对 需要加密的参数 进行加密
 * @param {string} word - 需要加密的参数，这里最好用JSON.stringify序列化
 * @param {string} key - 加密密钥（长度必须是 16 的整数倍，这里我们可以用uuid）
 */
export function aseEncryptParams(word, key) {
    // 加密的参数 - 从 UTF-8编码 解析出原始字符串
    const wordUTF8 = CryptoJS.enc.Utf8.parse(word);
    // 密钥 - 从 UTF-8编码 解析出原始字符串
    const keyUTF8 = CryptoJS.enc.Utf8.parse(key);

    const encrypted = CryptoJS.AES.encrypt(wordUTF8, keyUTF8, {
        mode: CryptoJS.mode.ECB,
        padding: CryptoJS.pad.Pkcs7,
    });

    return encrypted.toString();
}


/**
 * ASE解密
 * @description 使用加密秘钥，对 需要解密的参数 进行解密
 * @param {string} encryptedWord - 需要解密的参数
 * @param {string} key - 加密密钥（长度必须是 16 的整数倍）
 */
export function aesDecryptParams(encryptedWord, key) {
    // 密钥 - 从 UTF-8编码 解析出原始字符串
    const keyUTF8 = CryptoJS.enc.Utf8.parse(key);

    const bytes = CryptoJS.AES.decrypt(encryptedWord, keyUTF8, {
        mode: CryptoJS.mode.ECB,
        padding: CryptoJS.pad.Pkcs7,
    });

    return JSON.parse(bytes.toString(CryptoJS.enc.Utf8))
}

/**
 * 生成 UUID
 * @returns {string}
 */
export function generateUUID() {
    var d = new Date().getTime();
    if (typeof performance !== 'undefined' && typeof performance.now === 'function') {
        d += performance.now();
    }
    return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
        var r = (d + Math.random() * 16) % 16 | 0;
        d = Math.floor(d / 16);
        return (c === 'x' ? r : (r & 0x3 | 0x8)).toString(16);
    });
}


/**
 * 格式化时间
 * @param {string} inputFormat 输入时间的格式
 * @param {string} inputTime 需要格式化的时间
 * @param {string} outputFormat 需要的输出格式
 * @returns {string} 格式化后的时间
 * 示例用法:
 * const inputFormat = 'yyyy-MM-dd HH:mm:ss';
 * const inputTime = '2024-06-04 00:00:00';
 * const outputFormat = 'yyyy-MM-dd HH:mm:ss';
 * const formattedTime = formatDateString(inputFormat, inputTime, outputFormat);
 * console.log(formattedTime); // 输出: 2024-06-04 00:00:00
 *
 */
export function formatDateString(inputFormat, inputTime, outputFormat) {
    // 解析输入的时间字符串
    const date = parseDate(inputFormat, inputTime);

    // 格式化为需要的输出格式
    return formatDate(outputFormat, date);
}

/**
 * 解析时间字符串为Date对象
 * @param {string} format 时间格式
 * @param {string} time 时间字符串
 * @returns {Date} Date对象
 */
function parseDate(format, time) {
    const formatTokens = format.match(/(yyyy|MM|dd|HH|mm|ss)/g);
    const dateTokens = time.match(/\d+/g);

    const dateMap = {};
    formatTokens.forEach((token, index) => {
        dateMap[token] = parseInt(dateTokens[index], 10);
    });

    return new Date(
        dateMap['yyyy'] || 1970,
        (dateMap['MM'] || 1) - 1,
        dateMap['dd'] || 1,
        dateMap['HH'] || 0,
        dateMap['mm'] || 0,
        dateMap['ss'] || 0
    );
}


/**
 * 格式化Date对象为指定格式的字符串
 * @param {string} format 时间格式
 * @param {Date} date Date对象
 * @returns {string} 格式化后的时间字符串
 */
function formatDate(format, date) {
    const formatMap = {
        yyyy: date.getFullYear(),
        MM: ('0' + (date.getMonth() + 1)).slice(-2),
        dd: ('0' + date.getDate()).slice(-2),
        HH: ('0' + date.getHours()).slice(-2),
        mm: ('0' + date.getMinutes()).slice(-2),
        ss: ('0' + date.getSeconds()).slice(-2)
    };

    return format.replace(/(yyyy|MM|dd|HH|mm|ss)/g, (token) => formatMap[token]);
}

/**
 * 获取当前时间并格式化为 "YYYY-MM-DD HH:MM:SS"
 * @returns {string} - 当前时间的字符串 (格式: "YYYY-MM-DD HH:MM:SS")
 */
export function getCurrentFormattedTime() {
    const date = new Date();

    const year = date.getFullYear();
    const month = String(date.getMonth() + 1).padStart(2, '0');
    const day = String(date.getDate()).padStart(2, '0');
    const hours = String(date.getHours()).padStart(2, '0');
    const minutes = String(date.getMinutes()).padStart(2, '0');
    const seconds = String(date.getSeconds()).padStart(2, '0');

    return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
}




/**
 * 计算给定时间延后若干分钟后的时间
 * @param {string} time - 输入时间，可以是字符串 (格式: "YYYY-MM-DD HH:MM:SS") 或 Date 对象
 * @param {number} minutes - 延后的分钟数
 * @returns {string} - 新时间的字符串 (格式: "YYYY-MM-DD HH:MM:SS")
 */
export function addMinutesToTime(time, minutes) {
    let date;
    // 检查输入时间的类型
    if (typeof time === 'string') {
        date = new Date(time.replace(/-/g, '/')); // 兼容不同浏览器
    }

    // 增加分钟数
    date.setMinutes(date.getMinutes() + minutes);

    // 格式化输出时间字符串
    const year = date.getFullYear();
    const month = String(date.getMonth() + 1).padStart(2, '0');
    const day = String(date.getDate()).padStart(2, '0');
    const hours = String(date.getHours()).padStart(2, '0');
    const minutesStr = String(date.getMinutes()).padStart(2, '0');
    const seconds = String(date.getSeconds()).padStart(2, '0');

    return `${year}-${month}-${day} ${hours}:${minutesStr}:${seconds}`;
}

/**
 * 从格式为 "X分钟" 的字符串中提取出数字
 * @param {string} timeStr - 输入的时间字符串 (格式: "X分钟")
 * @returns {number} - 提取出的数字
 */
export function extractMinutes(timeStr) {
    const regex = /(\d+)\s*分钟/;
    const match = timeStr.match(regex);
    return match ? parseInt(match[1], 10) : null;
}

/**
 * 截取日期部分
 * @param dateStr
 * @returns {*}
 */
export function truncateDate(dateStr) {
    if(dateStr) {
        return dateStr.split(' ')[0];
    }
}

export function debounce(func, wait, immediate) {
    let timeout, args, context, timestamp, result

    const later = function() {
        // 据上一次触发时间间隔
        const last = +new Date() - timestamp

        // 上次被包装函数被调用时间间隔 last 小于设定时间间隔 wait
        if (last < wait && last > 0) {
            timeout = setTimeout(later, wait - last)
        } else {
            timeout = null
            // 如果设定为immediate===true，因为开始边界已经调用过了此处无需调用
            if (!immediate) {
                result = func.apply(context, args)
                if (!timeout) context = args = null
            }
        }
    }

    return function(...args) {
        context = this
        timestamp = +new Date()
        const callNow = immediate && !timeout
        // 如果延时不存在，重新设定延时
        if (!timeout) timeout = setTimeout(later, wait)
        if (callNow) {
            result = func.apply(context, args)
            context = args = null
        }

        return result
    }
}